package com.edgar.plugin.pm;

import android.content.Context;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.Package;
import android.os.Build;

import com.edgar.plugin.utils.MethodUtils;
import com.edgar.plugin.utils.Utils;

import java.io.File;

/**
 * Created by Edgar on 2018/2/8.
 */
public final class PackageParserCompat {

    private static IPackageParser sPackageParser;

    private PackageParserCompat(){}

    public static IPackageParser get(){
        if (sPackageParser == null){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
                sPackageParser = new PackageParserV24();
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
                sPackageParser = new PackageParserV21();
            } else {
                sPackageParser = new PackageParserLegacy();
            }
        }
        return sPackageParser;
    }

    public static abstract class IPackageParser {
        public abstract Package parsePackage(Context context,File sourceFile,int flags)throws PackageParser.PackageParserException;
        public int getParseError(){return -1;}
    }

    private static class PackageParserV24 extends IPackageParser{

        @Override
        public Package parsePackage(Context context, File sourceFile, int flags) throws PackageParser.PackageParserException {
            PackageParser packageParser = new PackageParser();
            packageParser.setDisplayMetrics(Utils.getDisplayMetrics(context));
            Package pkg = packageParser.parsePackage(sourceFile,flags);
            try {
                MethodUtils.invokeStaticMethodThrowError(PackageParser.class,"collectCertificates",new Class[]{pkg.getClass(),int.class},pkg,flags);
            } catch (Exception e){
                final Throwable cause = e.getCause();
                String message = cause != null ? cause.getMessage():e.getMessage();
                throw new PackageParser.PackageParserException(-1,message,cause);
            }
            return pkg;
        }
    }

    private static class PackageParserV21 extends IPackageParser{
        @Override
        public Package parsePackage(Context context, File sourceFile, int flags) throws PackageParser.PackageParserException {
            PackageParser packageParser = new PackageParser();
            packageParser.setDisplayMetrics(Utils.getDisplayMetrics(context));
            Package pkg = packageParser.parsePackage(sourceFile,flags);
            packageParser.collectCertificates(pkg,flags);
            return pkg;
        }
    }

    private static class PackageParserLegacy extends IPackageParser {
        private int mParseError;

        @Override
        public int getParseError() {
            return mParseError;
        }

        @Override
        public Package parsePackage(Context context, File sourceFile, int flags)throws PackageParser.PackageParserException {
            PackageParser packageParser = new PackageParser(sourceFile.getPath());
            Package pkg = packageParser.parsePackage(sourceFile,sourceFile.getPath(),context.getResources().getDisplayMetrics(),flags);
            mParseError = packageParser.getParseError();
            if (pkg != null){
                MethodUtils.invokeMethod(packageParser, "collectCertificates",
                        new Class[]{pkg.getClass(), int.class}, pkg, flags);
            }
            return pkg;
        }
    }
}